package com.boatAnchorAssistant.service.service.impl;

import com.boatAnchorAssistant.pojo.dto.authorization.GetAuthorizedByTargetIdDto;
import com.boatAnchorAssistant.pojo.entity.Authorization;
import com.boatAnchorAssistant.pojo.entity.Resource;
import com.boatAnchorAssistant.pojo.enums.authorized.AuthorizedTypeEnum;
import com.boatAnchorAssistant.pojo.param.authorization.AuthorizationParam;
import com.boatAnchorAssistant.pojo.param.authorization.GetAuthorizedTreeParam;
import com.boatAnchorAssistant.pojo.vo.authorization.AuthorizedVo;
import com.boatAnchorAssistant.pojo.vo.authorization.CurrentUserPageResourceVo;
import com.boatAnchorAssistant.pojo.vo.authorization.GetAuthorizedTreeVo;
import com.boatAnchorAssistant.service.repository.in.*;
import com.boatAnchorAssistant.service.service.in.AuthorizationService;
import nirvana.core.context.WebContext;
import nirvana.core.utils.copy.BeanTools;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 【描 述】：
 * 【环 境】：J2SE 17
 * 【详 细】：
 *
 * @author 李松林
 * @version v1.0 2024/5/3 新建
 * @since 2024/5/3
 */
@Service
public class AuthorizationServiceImpl implements AuthorizationService {

    private final AuthorizationRepository authorizationRepository;
    private final RoleRepository roleRepository;
    private final UserRepository userRepository;
    private final ResourceRepository resourceRepository;
    private final TenantRepository tenantRepository;
    private final ApplicationEventPublisher publisher;

    public AuthorizationServiceImpl(AuthorizationRepository authorizationRepository, RoleRepository roleRepository, UserRepository userRepository, ResourceRepository resourceRepository, TenantRepository tenantRepository, ApplicationEventPublisher publisher) {
        this.authorizationRepository = authorizationRepository;
        this.roleRepository = roleRepository;
        this.userRepository = userRepository;
        this.resourceRepository = resourceRepository;
        this.tenantRepository = tenantRepository;
        this.publisher = publisher;
    }


    /**
     * 授权
     *
     * @param param
     */
    @Override
    public void authorization(AuthorizationParam param) {
        Long targetId = param.getTargetId();
        AuthorizedTypeEnum authorizationType = param.getAuthorizationType();
        List<Long> resourceIds = param.getResourceIds();

        //清理
        authorizationRepository.clear(targetId, authorizationType);

        //添加的授权
        List<Authorization> createList = new ArrayList<>();
        //获取需要新增的授权列表
        for (Long resourceId : resourceIds) {
            //在已授权的列表中进行查看
            Authorization authorization = new Authorization();
            authorization.setTargetId(targetId);
            authorization.setResourceId(resourceId);
            authorization.setId(IdGenerator.SNOW.generate());

            Integer authorizedValue = 0;
            if (AuthorizedTypeEnum.ALLOW.equals(authorizationType)) {
                //取消允许
                authorizedValue = 1;
            } else {
                //取消禁止
                authorizedValue = -2;
            }
            authorization.setAuthorizedValue(authorizedValue);
            createList.add(authorization);
        }

        authorizationRepository.saveBatch(createList);
    }

    /**
     * 获取被授权的树形图
     *
     * @param param
     * @return
     */
    @Override
    public GetAuthorizedTreeVo getAuthorizedTree(GetAuthorizedTreeParam param) {
        AuthorizedTypeEnum authorizationType = param.getAuthorizationType();
        Long targetId = param.getTargetId();


        GetAuthorizedByTargetIdDto dto = new GetAuthorizedByTargetIdDto();
        dto.setAuthorizedType(authorizationType);
        dto.setTargetId(targetId);

        //单一类型授权列表
        Map<Long, Integer> authorizedMap = authorizationRepository.getAuthorizedMap(dto);


        //获取全部资源
        // TODO: 2022-07-05 这里论证一下，是否需要在禁用时，只能禁用被允许的资源
        List<Resource> resources = resourceRepository.getListByEntity(new Resource());


        List<AuthorizedVo> list = new ArrayList<>();

        //判断是否授权
        for (Resource resource : resources) {
            Long resourceId = resource.getId();

            Integer authValue = authorizedMap.get(resourceId);
            if (authValue == null) {
                authValue = 0;
            }

            AuthorizedVo vo = new AuthorizedVo();
            BeanUtils.copyProperties(resource,vo);

            //判断是否有此项授权
            vo.setChecked(authValue != 0);
            list.add(vo);
        }


        Map<Long, List<AuthorizedVo>> resourceAuthorizedMap = list.stream().collect(Collectors.groupingBy(AuthorizedVo::getParentId));
        //拼接树形图
        for (AuthorizedVo vo : list) {
            Long resourceId = vo.getId();
            List<AuthorizedVo> child = resourceAuthorizedMap.get(resourceId);
            if (CollectionUtils.isEmpty(child)) {
                child = Collections.EMPTY_LIST;
            }
            vo.setChild(child);
        }

        list = resourceAuthorizedMap.get(0L);
        List<Long> resourceIds = authorizedMap.keySet().stream().collect(Collectors.toList());
        GetAuthorizedTreeVo vo=new GetAuthorizedTreeVo();
        vo.setList(list);
        vo.setResourceIds(resourceIds);

        return vo;
    }

    /**
     * 获取当前用户被授权页面
     *
     * @return
     */
    @Override
    public List<CurrentUserPageResourceVo> getCurrentUserPageResource() {
        //获取用户的全部角色
        List<Long> roleIds = roleRepository.getRoleIdsListByUserId(WebContext.getCurrentUserId());

        //获取角色所有可用资源id
        List<Long> resourceIds = authorizationRepository.getAvailableResourceByTargetIds(roleIds);

        //添加默认资源
        Resource t = new Resource();
        t.setDefaultResource(Boolean.TRUE);
        List<Long> defaultResourceList = resourceRepository.getListByEntity(t)
                .stream()
                .map(Resource::getId)
                .collect(Collectors.toList());
        defaultResourceList.addAll(resourceIds);

        //查询资源
        List<Resource> resourceList = resourceRepository.getPageResourceListByIds(resourceIds);

        List<CurrentUserPageResourceVo> list = BeanTools.copyListProperties(resourceList, CurrentUserPageResourceVo::new);
        //组装树结构
        Map<Long, List<CurrentUserPageResourceVo>> listMap = list.stream()
                .collect(Collectors.groupingBy(CurrentUserPageResourceVo::getParentId));

        for (CurrentUserPageResourceVo vo : list) {
            Long id = vo.getId();
            List<CurrentUserPageResourceVo> voList = listMap.get(id);
            vo.setChild(voList);
        }
        list = listMap.get(0L);
        if (CollectionUtils.isEmpty(list)) {
            list = Collections.EMPTY_LIST;
        }
        return list;
    }

    /**
     * 批量移除某些对象的授权
     *
     * @param targetIds
     */
    @Override
    public void bathRemoveTargetAuthorized(List<Long> targetIds) {
        authorizationRepository.bathRemoveTargetAuthorized(targetIds);
    }
}
